package com.example.server.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.server.web.domain.QuestionnaireSummary;
import com.example.server.web.domain.SysUser;
import com.example.server.web.domain.Teacher;
import com.example.server.web.domain.page.PageQueryDto;
import com.example.server.web.domain.dto.QuestionnaireSummaryDto;
import com.example.server.web.domain.dto.QuestionnaireSummaryMutilDto;
import com.example.server.web.domain.vo.QuestionnaireSummaryMutilVo;
import com.example.server.web.domain.vo.QuestionnaireSummaryVo;
import com.example.server.web.exception.CustomException;
import com.example.server.web.service.QuestionnaireSummaryService;
import com.example.server.web.mapper.QuestionnaireSummaryMapper;
import com.example.server.web.service.SysUserService;
import com.example.server.web.service.TeacherService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author YHJ
* @description (问卷汇总) 服务实现类
*/
@Service
public class QuestionnaireSummaryServiceImpl extends ServiceImpl<QuestionnaireSummaryMapper, QuestionnaireSummary>
    implements QuestionnaireSummaryService{

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private SysUserService userService;

    @Resource
    private QuestionnaireSummaryMapper summaryMapper;

    @Override
    public Map<String, Object> getPage(PageQueryDto pageQueryDto, QuestionnaireSummaryDto summaryDto) {
        String year = summaryDto.getYear();
        if (StringUtils.isBlank(year)){
            throw new CustomException("年度不能为空");
        }
        QuestionnaireSummaryVo vo = new QuestionnaireSummaryVo();
        //判断请求参数是否有教师编号
        String teacherUserName = summaryDto.getTeacherUserName();
        if (StringUtils.isNotBlank(teacherUserName)){
            //先查询用户
            SysUser user = userService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, teacherUserName));
            if (ObjectUtils.isEmpty(user)){
                return mapNull();
            }
            //再查询教师
            Teacher teacher = teacherService.getOne(new LambdaQueryWrapper<Teacher>().eq(Teacher::getUserId, user.getId()));
            if (ObjectUtils.isEmpty(teacher)){
                return mapNull();
            }
            //获取教师id
            Long teacherId = teacher.getId();
            //分页查询
            LambdaQueryWrapper<QuestionnaireSummary> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(QuestionnaireSummary::getTeacherId,teacherId);
            wrapper.eq(QuestionnaireSummary::getYear,year);
            Map<String, Object> map = getMapByWrapper(pageQueryDto, wrapper);
            //****计算教学个人平均分
            //1、先计算教学个人总分
            List<QuestionnaireSummary> summaries = summaryMapper.selectList(wrapper);
            if (CollectionUtils.isEmpty(summaries)) {
                map.put("vo",vo);
                return map;
            }
            //2、计算教学个人平均分
            BigDecimal totalScore = summaries.stream().map(item -> item.getTotalScore()).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal personAvgScore = totalScore.divide(BigDecimal.valueOf(summaries.size()), 2, RoundingMode.HALF_UP);
            vo.setPersonAvgScore(personAvgScore);

            //****计算全校教师平均分
            BigDecimal schoolTeaAvgSchool = getSchoolTeaAvgScore(year);
            vo.setSchoolTeaAvgScore(schoolTeaAvgSchool);
            map.put("vo",vo);
            return map;
        } else if (summaryDto.getClassId() != null){
            Long classId = summaryDto.getClassId();
            //分页查询
            LambdaQueryWrapper<QuestionnaireSummary> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(QuestionnaireSummary::getClassId,classId);
            wrapper.eq(QuestionnaireSummary::getYear,year);
            Map<String, Object> map = getMapByWrapper(pageQueryDto, wrapper);
            //计算参加评教人数
            Integer classTeacherNum = summaryMapper.getClassTeacherNum(year,classId);
            vo.setClassTeacherNum(classTeacherNum);
            //计算院内教师平均分
            //判断分页是否有数据
            if ((Long)map.get("total") <= 0L){
                map.put("vo",vo);
                return map;
            }
            //取出第一条数据，获取学院id
            List<QuestionnaireSummary> list = (List<QuestionnaireSummary>) map.get("list");
            Long academyId = list.get(0).getAcademyId();
            //计算学院教师评测平均分
            BigDecimal academyAvgScore = getAcademyAvgScore(year, academyId);
            vo.setAcademyAvgScore(academyAvgScore);
            //计算班级教师评测平均分
            BigDecimal classAvgScore = getClassAvgScore(year, classId);
            vo.setClassAvgScore(classAvgScore);
            map.put("vo",vo);
            return map;
        } else if (summaryDto.getAcademyId() != null){
            Long academyId = summaryDto.getAcademyId();
            //分页查询
            LambdaQueryWrapper<QuestionnaireSummary> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(QuestionnaireSummary::getAcademyId,academyId);
            wrapper.eq(QuestionnaireSummary::getYear,year);
            Map<String, Object> map = getMapByWrapper(pageQueryDto, wrapper);
            //获取全学院老师评教平均分
            BigDecimal academyAvgScore = getAcademyAvgScore(year, academyId);
            vo.setAcademyAvgScore(academyAvgScore);
            //获取全校老师评教平均分
            BigDecimal schoolTeaAvgSchool = getSchoolTeaAvgScore(year);
            vo.setSchoolTeaAvgScore(schoolTeaAvgSchool);
            //获取学院老师参与评测人数
            Integer academyTeacherNum = summaryMapper.getAcademyTeacherNum(year, academyId);
            vo.setAcademyTeacherNum(academyTeacherNum);
            map.put("vo",vo);
            return map;
        }
        LambdaQueryWrapper<QuestionnaireSummary> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QuestionnaireSummary::getYear,year);
        Map<String, Object> map = getMapByWrapper(pageQueryDto, wrapper);
        map.put("vo",vo);
        return map;
    }

    /**
     * 计算班级教师评测平均分
     * @param year
     * @param classId
     * @return
     */
    private BigDecimal getClassAvgScore(String year, Long classId) {
        //组件条件
        LambdaQueryWrapper<QuestionnaireSummary> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QuestionnaireSummary::getYear,year);
        wrapper.eq(QuestionnaireSummary::getClassId,classId);
        return getAvg(wrapper);
    }

    /**
     * 查询学院教师评测平均分
     * @return
     */
    private BigDecimal getAcademyAvgScore(String year,Long academyId) {
        //组件条件
        LambdaQueryWrapper<QuestionnaireSummary> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QuestionnaireSummary::getYear,year);
        wrapper.eq(QuestionnaireSummary::getAcademyId,academyId);
        return getAvg(wrapper);
    }

    /**
     * 根据查询条件查询分页信息
     * @param pageQueryDto
     * @param wrapper
     * @return
     */
    private Map<String, Object> getMapByWrapper(PageQueryDto pageQueryDto, LambdaQueryWrapper<QuestionnaireSummary> wrapper) {
        Page<QuestionnaireSummary> page = this.page(new Page<>(pageQueryDto.getPage(), pageQueryDto.getLimit()), wrapper);
        Map<String, Object> map = new HashMap<>();
        map.put("list",page.getRecords());
        map.put("total",page.getTotal());
        return map;
    }

    /**
     * 获得全校教师平均分
     * @return
     */
    private BigDecimal getSchoolTeaAvgScore(String year){
        LambdaQueryWrapper<QuestionnaireSummary> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(QuestionnaireSummary::getYear,year);
        return getAvg(wrapper);
    }

    /**
     * 根据查询条件查询，再获取平均分
     * @param wrapper
     * @return
     */
    private BigDecimal getAvg(LambdaQueryWrapper<QuestionnaireSummary> wrapper) {
        List<QuestionnaireSummary> summaries = this.list(wrapper);
        if (CollectionUtils.isEmpty(summaries)) {
            return BigDecimal.ZERO;
        }
        BigDecimal reduce = summaries.stream().map(item -> item.getTotalScore()).reduce(BigDecimal.ZERO, BigDecimal::add);
        return reduce.divide(BigDecimal.valueOf(summaries.size()), 2, RoundingMode.HALF_UP);
    }

    /**
     * 返回空map
     * @return
     */
    private Map<String,Object> mapNull(){
        Map<String, Object> map = new HashMap<>();
        map.put("list",null);
        map.put("total",0);
        map.put("vo",new QuestionnaireSummaryVo());
        return map;
    }

    @Override
    public Map<String, Object> getPageMulti(QuestionnaireSummaryMutilDto summaryDto) {
        Map<String, Object> map = new HashMap<>();
        //判断年份
        if (summaryDto.getYearDimension() == null || summaryDto.getYearDimension().length <= 0){
            throw new CustomException("请填写年份");
        }
        //查询
        List<QuestionnaireSummaryMutilVo> mutilVoList = summaryMapper.getPageMulti(summaryDto);
        //根据年份分组
        if (CollectionUtils.isEmpty(mutilVoList)){
            map.put("vo",null);
            return map;
        }
        //根据年份分组
        Map<String, List<QuestionnaireSummaryMutilVo>> voMap = mutilVoList.stream().collect(Collectors.groupingBy(QuestionnaireSummaryMutilVo::getYear));
        //判断是否根据专业分组
        String academicDimension = summaryDto.getAcademicDimension();
        if (StringUtils.isNotBlank(academicDimension)){
            if ("0".equals(academicDimension)){
                //****根据学院分组
                //自定义Function
                Function<QuestionnaireSummaryMutilVo, String> academyFun = item -> item.getAcademyName();
                //进行下一级分组
                voMap = getGroupNew(voMap,academyFun);
            } else if ("1".equals(academicDimension)){
                //****根据专业分组
                //自定义Function
                Function<QuestionnaireSummaryMutilVo, String> majorFun = item -> item.getMajorName();
                //进行下一级分组
                voMap = getGroupNew(voMap,majorFun);
            } else {
                throw new CustomException("教务维度参数传入有误");
            }
        }

        //判断是否根据教师维度进行分组
        String teacherDimension = summaryDto.getTeacherDimension();
        if (StringUtils.isNotBlank(teacherDimension)){
            if ("0".equals(teacherDimension)){
                //****根据性别分组
                //自定义Function
                Function<QuestionnaireSummaryMutilVo, String> sexFun = item -> item.getSex();
                //进行下一级分组
                voMap = getGroupNew(voMap,sexFun);
            } else if ("1".equals(teacherDimension)){
                //****根据职称分组
                //自定义Function
                Function<QuestionnaireSummaryMutilVo, String> titleFun = item -> item.getTitle();
                //进行下一级分组
                voMap = getGroupNew(voMap,titleFun);
            } else if ("2".equals(teacherDimension)){
                //****根据学历分组
                //自定义Function
                Function<QuestionnaireSummaryMutilVo, String> qualificationFun = item -> item.getQualification();
                //进行下一级分组
                voMap = getGroupNew(voMap,qualificationFun);
            } else if ("3".equals(teacherDimension)){
                //****根据年龄分组
                //自定义Function
                Function<QuestionnaireSummaryMutilVo, String> ageFun = item -> (item.getAge().toString());
                //进行下一级分组
                voMap = getGroupNew(voMap,ageFun);
            }else {
                throw new CustomException("教师维度参数传入有误");
            }
        }

        //统计分数
        List<QuestionnaireSummaryMutilVo> list = new ArrayList<>();
        Set<String> keySet = voMap.keySet();
        for (String key : keySet) {
            //取出多级分组后的数据
            List<QuestionnaireSummaryMutilVo> voList = voMap.get(key);
            if (CollectionUtils.isEmpty(voList)){
                continue;
            }
            //取出第一条数据
            QuestionnaireSummaryMutilVo oneVo = voList.get(0);
            QuestionnaireSummaryMutilVo mutilVo = new QuestionnaireSummaryMutilVo();
            BeanUtils.copyProperties(oneVo,mutilVo);
            //初始化分数
            BigDecimal attitudeScore = BigDecimal.ZERO;
            BigDecimal contentScore = BigDecimal.ZERO;
            BigDecimal methodScore = BigDecimal.ZERO;
            BigDecimal resultScore = BigDecimal.ZERO;
            BigDecimal totalScore = BigDecimal.ZERO;
            for (QuestionnaireSummaryMutilVo item : voList) {
                attitudeScore = attitudeScore.add(item.getAttitudeScore());
                contentScore = contentScore.add(item.getContentScore());
                methodScore = methodScore.add(item.getMethodScore());
                resultScore = resultScore.add(item.getResultScore());
                totalScore = totalScore.add(item.getTotalScore());
            }
            //该分组下的教师参与评测人数
            int size = voList.size();
            //计算平均分
            mutilVo.setAttitudeScore(attitudeScore.divide(BigDecimal.valueOf(size),2,RoundingMode.HALF_UP));
            mutilVo.setContentScore(contentScore.divide(BigDecimal.valueOf(size),2,RoundingMode.HALF_UP));
            mutilVo.setMethodScore(methodScore.divide(BigDecimal.valueOf(size),2,RoundingMode.HALF_UP));
            mutilVo.setResultScore(resultScore.divide(BigDecimal.valueOf(size),2,RoundingMode.HALF_UP));
            mutilVo.setTotalScore(totalScore.divide(BigDecimal.valueOf(size),2,RoundingMode.HALF_UP));
            list.add(mutilVo);
        }
        map.put("list",list);
        return map;
    }

    /**
     * 进行下一级分组
     * @param voMap
     * @param function
     * @return
     */
    private Map<String, List<QuestionnaireSummaryMutilVo>> getGroupNew(Map<String, List<QuestionnaireSummaryMutilVo>> voMap,Function<QuestionnaireSummaryMutilVo, String> function) {
        Map<String, List<QuestionnaireSummaryMutilVo>> tempMap = new HashMap<>();
        //遍历不同组的key
        Set<String> keySet = voMap.keySet();
        for (String key:keySet){
            //根据条件分组
            List<QuestionnaireSummaryMutilVo> voList = voMap.get(key);
            Map<String, List<QuestionnaireSummaryMutilVo>> tempMap2 = voList.stream().collect(Collectors.groupingBy(function));
            //****组成新的key,再放进临时map中
            Set<String> tempKey2 = tempMap2.keySet();
            //1、遍历
            for (String key2:tempKey2){
                //2、组成新的key：旧的key+新分组的key   如旧的key：2021-2022 + 新分组的key：计算机科学学院  = 2021-2022/计算机科学学院
                String tempKey = key2 +"/"+ key;
                tempMap.put(tempKey,tempMap2.get(key2));
            }
        }
        return tempMap;
    }
}




